package com.roadmap.client.module.user;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.roadmap.common.BaseConst;
import com.roadmap.common.BaseEntity;
import com.roadmap.common.RdcLogger;
import com.roadmap.common.RdcResourceBundle;
import com.roadmap.common.BaseEnum.ActionType;
import com.roadmap.entities.Achievement;
import com.roadmap.entities.Activity;
import com.roadmap.entities.Article;
import com.roadmap.entities.Aspirant;
import com.roadmap.entities.Assessment;
import com.roadmap.entities.Career;
import com.roadmap.entities.LifeGoal;
import com.roadmap.entities.LifeMap;
import com.roadmap.entities.LifePlan;
import com.roadmap.entities.LifeTask;
import com.roadmap.entities.Student;
import com.roadmap.entities.Summary;
import com.roadmap.exception.InvalidActionException;
import com.roadmap.exception.InvalidQueryException;
import com.roadmap.exception.InvalidValueException;
import com.roadmap.exception.NullObjectException;
import com.roadmap.exception.ServerException;
import com.roadmap.repo.db.DatabaseUtility;
import com.roadmap.repo.db.IDatabaseUtility;

/** record user's actions */
@Deprecated
public class ActRecorder implements IActRecorder {
	private final static Logger logger = RdcLogger.getLogger(ActRecorder.class);
	private final IDatabaseUtility dbUtil;
	/**
	 * when aspirant updates his data, his activity will be recorded
	 * automatically, but not all entities he updates
	 */
	private final static Hashtable<Class, String> entitiesCanbeRecorded = new Hashtable<Class, String>();
	private final static Hashtable<ActionType, String> actionNames = new Hashtable<ActionType, String>();
	/** whose activities should be recorded */
	private String aspirantId;
	// private static boolean isNotConfigured = true;
	private Aspirant aspirant;

	static {
		entitiesCanbeRecorded.put(Aspirant.class,
				RdcResourceBundle.LOCAL_NAME_ASPIRANT);
		entitiesCanbeRecorded.put(Achievement.class,
				RdcResourceBundle.LOCAL_NAME_ACHIEVEMENT);
		entitiesCanbeRecorded.put(Assessment.class,
				RdcResourceBundle.LOCAL_NAME_ASSEESSMENT);
		// entitiesCanbeRecorded.put(Execution.class,
		// RdcResourceBundle.LOCAL_NAME_EXEUCTION);
		entitiesCanbeRecorded.put(LifeMap.class,
				RdcResourceBundle.LOCAL_NAME_LIFEMAP);
		entitiesCanbeRecorded.put(LifeGoal.class,
				RdcResourceBundle.LOCAL_NAME_LIFEGOAL);
		entitiesCanbeRecorded.put(LifePlan.class,
				RdcResourceBundle.LOCAL_NAME_LIFEPLAN);
		entitiesCanbeRecorded.put(LifeTask.class,
				RdcResourceBundle.LOCAL_NAME_LIFETASK);
		entitiesCanbeRecorded.put(Summary.class,
				RdcResourceBundle.LOCAL_NAME_SUMMARY);
		entitiesCanbeRecorded.put(Career.class,
				RdcResourceBundle.LOCAL_NAME_PROFILE_CAREER);
		entitiesCanbeRecorded.put(Student.class,
				RdcResourceBundle.LOCAL_NAME_PROFILE_STUDENT);
		entitiesCanbeRecorded.put(Article.class,
				RdcResourceBundle.LOCAL_NAME_ARTICLE);

		actionNames.put(ActionType.CREATE, RdcResourceBundle.ACTION_CREATE);
		actionNames.put(ActionType.UPDATE, RdcResourceBundle.ACTION_UPDATE);
		actionNames.put(ActionType.DELETE, RdcResourceBundle.ACTION_DELETE);
		actionNames.put(ActionType.COMPLETE, RdcResourceBundle.ACTION_COMPLETE);
		actionNames.put(ActionType.BECOME, RdcResourceBundle.ACTION_BECOME);
	}

	// private final String aspName;

	public ActRecorder(String aspirantId) {
		this.dbUtil = new DatabaseUtility();
		this.aspirantId = aspirantId;
	}

	public ActRecorder(Aspirant aspirant) {
		this.dbUtil = new DatabaseUtility();
		this.aspirant = aspirant;
		this.aspirantId = aspirant.getId();
	}

	public ActRecorder(String aspirantId, IDatabaseUtility dbUtil) {
		this.aspirantId = aspirantId;
		this.dbUtil = dbUtil;
	}

	public Aspirant getAspirant() throws NullObjectException,
			InvalidQueryException, ServerException, InvalidValueException {
		if (aspirant == null || !aspirant.getId().equals(aspirantId)) {
			aspirant = (Aspirant) dbUtil.getEntityById(Aspirant.class,
					aspirantId);
		}
		return aspirant;
	}

	public void setAspirant(Aspirant asp) {
		this.aspirant = asp;
	}

	public IDatabaseUtility getDbUtil() {
		return dbUtil;
	}

	public String getAspirantId() {
		return aspirantId;
	}

	public void setAspirantId(String aspirantId) {
		this.aspirantId = aspirantId;
	}

	/**
	 * create a activity record when users create or update something.
	 * 
	 * @param entity:
	 *            [Achievement, Assessment, Execution, LifeMap, LifeGoal,
	 *            LifePlan, LifeTask, Summary]
	 * @param type:
	 *            [create, update]
	 */
	public void record(BaseEntity entity, ActionType type)
			throws InvalidValueException, InvalidActionException,
			ServerException {
		if (entity == null || aspirantId == null || type == null) {
			NullObjectException noe = new NullObjectException(
					"invalid inputs. they can't be NULL");
			logger.error(noe);
			throw noe;
		}

		// check if the entity and type should filtered
		if (filter(entity, type)) {
			return;
		}

		// create a new activity record
		Activity action = new Activity();
		action.setAspirantId(aspirantId);
		action.setUserOperation(getActionText(type));
		String content = entitiesCanbeRecorded.get(entity.getClass())
				+ Activity.getSeparator() + entity.getWhatItIs();
		action.setContent(content);
		action.setOperatedObject(entity.getClass().getSimpleName());
		action.setOperatedObjectId(entity.getId());

		dbUtil.save(action);

		/*
		 * // create a notice Notice notice = new Notice();
		 * notice.setDispatcherId(aspirantId);
		 * notice.setEntryType(entity.getClass().getSimpleName());
		 * notice.setEntryId(entity.getId()); String desc =
		 * entitiesCanbeRecorded.get(entity.getClass()) +
		 * Activity.getSeparator() + entity.getWhatItIs();
		 * notice.setEntryDesc(desc); notice.setActivity(getActionText(type));
		 */
	}

	/**
	 * this method filter some entities and action types if the entities and
	 * types don't satisfy the rules for generating a activity record
	 */
	private boolean filter(BaseEntity entity, ActionType type) {
		if (entitiesCanbeRecorded.containsKey(entity.getClass()) == false
				|| type == ActionType.UPDATE || type == ActionType.DELETE) {
			return true;
		}
		else {
			return false;
		}
	}

	private String getActionText(ActionType type) {
		return actionNames.get(type);
	}

	public List getActivityRecords() throws InvalidValueException,
			InvalidQueryException, ServerException {
		// activities = getAspirantActivities();
		// getFriendActivities();
		// String criteria = "aspirantId='" + aspirantId + "' order by
		// happenTime DESC limit ";
		// return dbUtil.getEntitiesByCriteria(Activity.class, criteria);
		/* modified on 2010-01-07 */
		String hql = "from Activity where aspirantId=? order by happenTime DESC";
		Object[] params = { aspirantId, 10 };
		return dbUtil.executeHQLQuery(hql, params);
	}

	public void delete(String actId) throws NullObjectException,
			ServerException, InvalidActionException {
		Activity act = new Activity();
		act.setId(actId);
		dbUtil.delete(act);
	}

	public Map<String, List> getActivities() throws InvalidValueException,
			InvalidQueryException, ServerException {
		// activities = getAspirantActivities();
		// getFriendActivities();
		Map<String, List> map = new HashMap<String, List>();
		// String criteria = "aspirantId='" + aspirantId
		// + "' order by happenTime DESC";
		// List results = dbUtil.getEntitiesByCriteria(Activity.class,
		// criteria);
		/* modified on 2010-01-07 */
		String hql = "from Activity where aspirantId=? order by happenTime DESC";
		Object[] params = { aspirantId };
		List results = dbUtil.executeHQLQuery(hql, params,
				BaseConst.MAX_RESULTS_IN_QUERY);
		map.put(aspirantId, results);
		return map;
	}
}
